package org.footballmanager.pandafootball.common.configure;

import com.alibaba.druid.pool.DruidDataSource;
import lombok.Getter;
import lombok.Setter;
import org.footballmanager.pandafootball.common.exception.ExceptionEnum;
import org.footballmanager.pandafootball.common.exception.MyException;
import org.quartz.SchedulerException;
import org.quartz.utils.ConnectionProvider;
import org.springframework.beans.factory.annotation.Value;

import java.sql.Connection;
import java.sql.SQLException;

/**
 * [Druid连接池的Quartz扩展类]
 *
 * @ProjectName: []
 * @Author: [xuguang]
 * @CreateDate: [2015/11/10 17:58]
 * @Update: [说明本次修改内容] BY[xuguang][2015/11/10]
 * @Version: [v1.0]
 */
@Setter
@Getter
public class DruidConnectionProvider implements ConnectionProvider {
    /* 数据库地址 */
    @Value("${spring.datasource.url}")
    protected String url;

    /* 数据库用户名 */
    @Value("${spring.datasource.username}")
    protected String user;

    /* 数据库密码 */
    @Value("${spring.datasource.password}")
    protected String password;

    /* 驱动名称 */
    @Value("${spring.datasource.driver-class-name}")
    protected String driver;


     /*
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     *
     * 常量配置，与quartz.properties文件的key保持一致(去掉前缀)，同时提供set方法，Quartz框架自动注入值。
     *
     * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     */

    //数据库最大连接数
    protected int maxConnection = 2;
    //数据库SQL查询每次连接返回执行到连接池，以确保它仍然是有效的。
    protected String validationQuery;

    protected boolean validateOnCheckout;

    protected int idleConnectionValidationSeconds;

    protected String maxCachedStatementsPerConnection;

    protected String discardIdleConnectionsSeconds;

    //Druid连接池
    protected DruidDataSource datasource;

    /*
    * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    *
    * 接口实现
    *
    * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    */
    public Connection getConnection() throws SQLException {
        return datasource.getConnection();
    }

    public void shutdown() throws SQLException {
        datasource.close();
    }

    public void initialize() throws SQLException{
        processError();

        datasource = new DruidDataSource();
        try{
            datasource.setDriverClassName(this.driver);
        } catch (Exception e) {
            try {
                throw new SchedulerException("Problem setting driver class name on datasource: " + e.getMessage(), e);
            } catch (SchedulerException e1) {
                throw new MyException(ExceptionEnum.CODEEXCEPTION, e1);
            }
        }

        datasource.setUrl(this.url);
        datasource.setUsername(this.user);
        datasource.setPassword(this.password);
        datasource.setMaxActive(this.maxConnection);
        datasource.setMinIdle(1);
        datasource.setMaxWait(0);
        datasource.setMaxPoolPreparedStatementPerConnectionSize(120);

        if (this.validationQuery != null) {
            datasource.setValidationQuery(this.validationQuery);
            if(!this.validateOnCheckout)
                datasource.setTestOnReturn(true);
            else
                datasource.setTestOnBorrow(true);
            datasource.setValidationQueryTimeout(this.idleConnectionValidationSeconds);
        }
    }

    private void processError() throws SQLException{
        if (this.url == null) {
            throw new SQLException("DBPool could not be created: DB URL cannot be null");
        }

        if (this.driver == null) {
            throw new SQLException("DBPool driver could not be created: DB driver class name cannot be null!");
        }

        if (this.maxConnection < 0) {
            throw new SQLException("DBPool maxConnectins could not be created: Max connections must be greater than zero!");
        }
    }
}
